﻿/*
    Copyright 2010, 2011 Eric Wong
	contact@optimalcycling.com
	http://www.optimalcycling.com
	Optimal Cycling - Advanced power pacing program for cyclists
	
	This file is part of Optimal Cycling.

    Optimal Cycling is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Optimal Cycling is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Optimal Cycling.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Runtime.InteropServices;
using Cloo;

namespace OptimalCycling
{
    #region Alias

    using sizeT = System.UInt32;
    using size_array = System.UInt32;

    // Allow us to easily switch between floats and double values
#if REAL_IS_DOUBLE
    using real = System.Double;
    using real2 = Vector2d;
    using real4 = Vector4d;
#else
    using real = System.Single;
    using real2 = Vector2;
    using real4 = Vector4;
#endif

    #endregion

    public static class DataConstants
    {
        public const real SMALL_REAL = (real)1E-7;
    }

    /// <summary>
    /// Holds the model information that stays the same for the simulation
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    [Serializable()]
    public struct ModelInfo
    {
        public real minSpeed;
        public real initialSpeed;
        public real massTotal;
        public real weightTotal;
        public real massAndRotInertiaTotal;
        public real inverseMassAndRotInertiaTotal;
        public real driveTrainEfficiency;
        public real CdA;
        public real halfCdA;
        public real diameterFrontWheel;
        public real diameterSqFrontWheel;
        public real rotInertiaFrontWheel;
        public real diameterRearWheel;
        public real diameterSqRearWheel;
        public real rotInertiaRearWheel;
        public real rearWheelShieldingFactor;
        public real oneMinusRearWheelShieldingFactor;
        public int stillWind;
    }

    /// <summary>
    /// Holds the constant options for the solver together that the kernel needs to know.
    /// </summary>
    #if REAL_IS_DOUBLE
        [StructLayout(LayoutKind.Sequential, Pack = 16)]
    #else
        [StructLayout(LayoutKind.Sequential, Pack = 8)]
    #endif
    [Serializable()]
    public struct SolverInfo
    {
        // Note that real2 types should be placed at the top or data corruption occurs
        public real2 diffEvoFLimits;
        public real2 diffEvoCrLimits;
        public real2 diffEvoSrLimits;

        // Butterworth limits
        public real2 bwCutOffF; 

        public sizeT heuristicSeedIndexLow;
        public sizeT heuristicSeedIndexHigh;

        public ulong maxGensToRun;

        public sizeT numIndividMigrate;
        public ulong gensPerMigration;

        public ulong convergenenceGenerations;
        public real convergenceTolerance;
    }


    /// <summary>
    /// Holds the params for the butterworth filter.
    /// </summary>
#if REAL_IS_DOUBLE
    [StructLayout(LayoutKind.Sequential, Pack = 16)]
#else
    [StructLayout(LayoutKind.Sequential, Pack = 8)]
#endif
    [Serializable()]
    public struct BwParams
    {
        // Note that real2 types should be placed at the top or data corruption occurs
        public real bwCutOffF;
        public real bwDataCollectF;
        public real bwW;
        public real bwK1;
        public real bwK2;
        public real bwK3;
        public real bwA0;
        public real bwA1;
        public real bwA2;
        public real bwB1;
        public real bwB2;
    }


    /// <summary>
    /// Holds the changing variables for the solver that the kernel needs to know.
    /// </summary>
#if REAL_IS_DOUBLE
    [StructLayout(LayoutKind.Sequential, Pack = 16)]
#else
    [StructLayout(LayoutKind.Sequential, Pack = 8)]
#endif
    [Serializable()]
    public struct SolverVars
    {
        public ulong currGen;
        public real maxTime;
        public sizeT raceTimeMeasureStartIndex;
    }

    /// <summary>
    /// Power metric parameters
    /// </summary>
    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    [Serializable()]
    public struct PowerMetricsInfo
    {
        public real posFactor;
        public real maxPosPowerRate;
        public real negFactor;
        public real minNegPowerRate;

        public real powerRateCoeff;
        public real powerRateExp;
        public real powerRateExpInverse;
        public real powerCurveExp;
        public real powerCurveExpInverse;
        public real ftp;

        public real gmExp;
        public real gmExpInverse;
        public real gmExpPlusOne;
        public real gmRollingAveTime;
        public int gmRollingAveIsExp;
        public real gmSamplingInterval;

        public PMTypes pmType;

        public sizeT numCriticals;        
    }

    /// <summary>
    /// What phase of the solving cycle we are currently performing
    /// </summary>
    public enum SolutionMode
    {
        SolutionMode_Initialize,
        SolutionMode_NoOptimize,
        SolutionMode_EvaluateFitness,
        SolutionMode_SortByFitness,
        SolutionMode_Mate,
        SolutionMode_OutputAll,
        SolutionMode_IncrementParams,
        SolutionMode_Migrate,
        SolutionMode_DiffEvo,
        SolutionMode_Test
    }

    /// <summary>
    /// What type of bearing resistance model to use
    /// </summary>
    public enum BearingResistance
    {
        BearingResistance_CartridgeBearingDahn,
        BearingResistance_None
    }

    /// <summary>
    /// What power metric types we can use
    /// </summary>
    public enum PMTypes
    {
        PMTypes_CCAP,
        PMTypes_Average,
        PMTypes_GeneralMean,
        PMTypes_NUM_COUNT
    }
}